const { loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { expect } = require("chai");
const { ethers } = require("hardhat");

const PROTOCOL_ADMIN_ROLE = ethers.keccak256(ethers.toUtf8Bytes("PROTOCOL_ADMIN"));

describe("ACLManager", function () {
  async function deployFixture() {
    const [deployer, user] = await ethers.getSigners();

    const ACLManagerFactory = await ethers.getContractFactory("ACLManager");
    const ACLManager = await ACLManagerFactory.deploy(deployer);
    await ACLManager.deploymentTransaction().wait();

    return { ACLManager, deployer, user };
  }

  describe("Deployment", function () {
    it("should deploy", async function () {
      const { ACLManager, deployer } = await loadFixture(deployFixture);

      expect(await ACLManager.hasRole(PROTOCOL_ADMIN_ROLE, deployer)).to.be.true;
    });
  });

  describe("Protocol Admins", function () {
    it("Admin isProtocolAdmin and isProtocolTrader", async function () {
      const { ACLManager, deployer } = await loadFixture(deployFixture);

      expect(await ACLManager.isProtocolAdmin(deployer)).to.be.true;
      expect(await ACLManager.isProtocolTrader(deployer)).to.be.true;
    });

    it("User is not the isProtocolAdmin and isProtocolTrader", async function () {
      const { ACLManager, user } = await loadFixture(deployFixture);

      expect(await ACLManager.isProtocolAdmin(user)).to.be.false;
      expect(await ACLManager.isProtocolTrader(user)).to.be.false;
    });
  });

  describe("Protocol Traders", function () {
    it("Return false to unregistered trader", async function () {
      const { ACLManager, user } = await loadFixture(deployFixture);

      expect(await ACLManager.isProtocolTrader(user)).to.be.false;
    });

    it("Register 1 trader", async function () {
      const { ACLManager, deployer } = await loadFixture(deployFixture);

      const randomUser = ethers.Wallet.createRandom();
      const txRegister = await ACLManager.connect(deployer).registerTraders([randomUser]);
      await txRegister.wait();

      expect(await ACLManager.isProtocolTrader(randomUser)).to.be.true;
    });

    it("Register 3 trader", async function () {
      const { ACLManager, deployer } = await loadFixture(deployFixture);

      let traders = [];
      for (let i = 0; i < 3; i++) {
        traders.push(ethers.Wallet.createRandom());
      }
      const txRegister = await ACLManager.connect(deployer).registerTraders(traders);
      await txRegister.wait();

      for (let i = 0; i < 3; i++) {
        expect(await ACLManager.isProtocolTrader(traders[i])).to.be.true;
      }
    });

    it("Revert if caller is not the protocol admin", async function () {
      const { ACLManager, deployer, user } = await loadFixture(deployFixture);

      const randomUser = ethers.Wallet.createRandom();
      await expect(ACLManager.connect(user).registerTraders([randomUser])).to.be.reverted;
    });
  });
});
